package com.sky.service.impl;

import com.sky.config.BaiduMapConfig;
import com.sky.constant.MessageConstant;
import com.sky.entity.AddressBook;
import com.sky.exception.OrderBusinessException;
import com.sky.service.BaiduMapService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * 百度地图服务实现类
 */
@Service
@Slf4j
public class BaiduMapServiceImpl implements BaiduMapService {
    
    @Autowired
    private BaiduMapConfig baiduMapConfig;
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Value("${sky.baidu-map.use-mock}")
    private Boolean useMock;
    
    // 模拟模式下的商家经纬度
    private static final double[] MOCK_SHOP_LOCATION = {39.9847, 116.3056}; // 北京市海淀区上地十街10号
    
    // 随机数生成器，用于模拟数据
    private Random random = new Random();

    @Override
    public boolean checkDeliveryRange(AddressBook addressBook) {
        if (addressBook == null || addressBook.getDetail() == null) {
            throw new OrderBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        
        // 获取商家地址和用户地址
        String shopAddress = baiduMapConfig.getShopAddress().getAddress();
        String userAddress = addressBook.getDetail();
        
        // 获取商家和用户的经纬度
        double[] shopLocation;
        double[] userLocation;
        
        if (useMock) {
            // 模拟模式
            shopLocation = MOCK_SHOP_LOCATION;
            // 模拟用户位置，在商家位置周围随机偏移
            userLocation = new double[] {
                shopLocation[0] + (random.nextDouble() - 0.5) * 0.1,
                shopLocation[1] + (random.nextDouble() - 0.5) * 0.1
            };
        } else {
            // 实际调用百度地图API
            shopLocation = getLocationByAddress(shopAddress);
            userLocation = getLocationByAddress(userAddress);
        }
        
        // 计算距离
        double distance;
        if (useMock) {
            // 模拟模式下随机生成0-10公里的距离
            distance = random.nextDouble() * 10;
        } else {
            distance = calculateDistance(
                shopLocation[0], shopLocation[1],
                userLocation[0], userLocation[1]
            );
        }
        
        log.info("计算商家与用户的距离: {} 公里", distance);
        
        // 模拟模式下80%的概率在配送范围内
        if (useMock) {
            return random.nextDouble() < 0.8;
        }
        
        // 判断是否在配送范围内
        double deliveryRadius = baiduMapConfig.getShopAddress().getDeliveryRadius();
        return distance <= deliveryRadius;
    }

    @Override
    public double[] getLocationByAddress(String address) {
        if (useMock) {
            // 模拟模式下返回固定经纬度或随机经纬度
            if (address.contains("上地十街10号")) {
                return MOCK_SHOP_LOCATION;
            } else {
                // 随机生成一个在北京附近的经纬度
                return new double[] {
                    39.9 + random.nextDouble() * 0.2,
                    116.3 + random.nextDouble() * 0.2
                };
            }
        }
        
        // 实际调用百度地图地理编码API
        String url = "http://api.map.baidu.com/geocoding/v3?address={address}&output=json&ak={ak}";
        Map<String, String> params = new HashMap<>();
        params.put("address", address);
        params.put("ak", baiduMapConfig.getAk());
        
        try {
            Map<String, Object> response = restTemplate.getForObject(url, Map.class, params);
            if (response != null && "0".equals(response.get("status").toString())) {
                Map<String, Object> result = (Map<String, Object>) response.get("result");
                Map<String, Double> location = (Map<String, Double>) result.get("location");
                return new double[] {location.get("lat"), location.get("lng")};
            }
        } catch (Exception e) {
            log.error("调用百度地图地理编码API失败: {}", e.getMessage());
        }
        
        throw new OrderBusinessException("获取地址经纬度失败");
    }

    @Override
    public double calculateDistance(double lat1, double lng1, double lat2, double lng2) {
        if (useMock) {
            // 模拟模式下随机生成距离
            return random.nextDouble() * 10;
        }
        
        // 实际调用百度地图路线规划API计算驾车距离
        String url = "http://api.map.baidu.com/routematrix/v2/driving?output=json&origins={origins}&destinations={destinations}&ak={ak}";
        Map<String, String> params = new HashMap<>();
        params.put("origins", lat1 + "," + lng1);
        params.put("destinations", lat2 + "," + lng2);
        params.put("ak", baiduMapConfig.getAk());
        
        try {
            Map<String, Object> response = restTemplate.getForObject(url, Map.class, params);
            if (response != null && "0".equals(response.get("status").toString())) {
                Map<String, Object> result = ((Map<String, Object>[]) response.get("result"))[0];
                Map<String, Object> distance = (Map<String, Object>) result.get("distance");
                // 百度地图API返回的距离单位是米，转换为公里
                return Double.parseDouble(distance.get("value").toString()) / 1000;
            }
        } catch (Exception e) {
            log.error("调用百度地图距离计算API失败: {}", e.getMessage());
        }
        
        // 如果API调用失败，使用Haversine公式计算直线距离
        return haversineDistance(lat1, lng1, lat2, lng2);
    }
    
    /**
     * 使用Haversine公式计算两点之间的直线距离
     */
    private double haversineDistance(double lat1, double lng1, double lat2, double lng2) {
        final int R = 6371; // 地球半径（公里）
        
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lng2 - lng1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        
        return R * c; // 返回公里
    }
}
